local VisualEffect = class("VisualEffect",function() return display.newNode() end)

local LocationConfig = import(".BattleLocation")
local Effect = import(".Effect")
local BuffView = import(".views.BuffView")

local NewerbattleguideController

-- VisualEffect.Event_SPAWN_EFFECT = "Event_SPAWN_EFFECT"
VisualEffect.Event_SKILL_INTERRUPTED = "Event_SKILL_INTERRUPTED"
VisualEffect.Event_SKILL_CANCEL_NO_MANA = "Event_SKILL_CANCEL_NO_MANA"

local USE_Effect_Cache = true
local USE_Buff_Effect_Cache = true


local Skill_ctx = battle.Skill.ctx
local Skill_id = battle.Skill.id
local Skill_uid = battle.Skill.uid
local Skill_unit = battle.Skill.unit
local Skill_targetId = battle.Skill.targetId
local Skill_getIsSubSkill = battle.Skill.getIsSubSkill
local Skill_isComboSkill = battle.Skill.isComboSkill
local Skill_getReleaseTargetPoint = battle.Skill.getReleaseTargetPoint
local Skill_getConfig = battle.Skill.cfg

local State_currentTime = battle.State.currentTime

local Entity_getId = battle.Entity.getId

local SkillConfig_getEffects = battle.SkillConfig.getEffects
local SkillConfig_getId = battle.SkillConfig.getId
local SkillConfig_isBasicAttack = battle.SkillConfig.isBasicAttack
local SkillConfig_getProjectiles = battle.SkillConfig.getProjectiles
local SkillConfig_getName = battle.SkillConfig.getName
local SkillConfig_getSummonEffectCfg = battle.SkillConfig.getSummonEffectCfg
local SkillConfig_getTransformEffectCfg = battle.SkillConfig.getTransformEffectCfg
local SkillConfig_isChanneled = battle.SkillConfig.isChanneled
local SkillConfig_chantD = battle.SkillConfig.chantD

local ProjectileConfig_getId = battle.ProjectileConfig.getId
local ProjectileConfig_getEffects = battle.ProjectileConfig.getEffects
local ProjectileConfig_getSummonEffectCfg = battle.ProjectileConfig.getSummonEffectCfg

local EffectConfig_getBengin = battle.EffectConfig.getBengin
local EffectConfig_getEnd = battle.EffectConfig.getEnd
local EffectConfig_getId = battle.EffectConfig.getId
local EffectConfig_getObjectCfg = battle.EffectConfig.getObjectCfg
local EffectConfig_getZorder = battle.EffectConfig.getZorder
local EffectConfig_getSfxFile = battle.EffectConfig.getSfxFile
local EffectConfig_getEffectSize = battle.EffectConfig.getEffectSize
local EffectConfig_getPlace = battle.EffectConfig.getPlace
local EffectConfig_getParam = battle.EffectConfig.getParam
local EffectConfig_getOffsetX = battle.EffectConfig.getOffsetX
local EffectConfig_getBlendFunc = battle.EffectConfig.getBlendFunc
local EffectConfig_getLine = battle.EffectConfig.getLine


local BuffConfig_getBuffEffectConfig = battle.BuffConfig.getBuffEffectConfig

local BuffEffectConfig_getId = battle.BuffEffectConfig.getId
local BuffEffectConfig_getBengin = battle.BuffEffectConfig.getBengin
local BuffEffectConfig_getEnd = battle.BuffEffectConfig.getEnd
local BuffEffectConfig_getActive = battle.BuffEffectConfig.getActive
local BuffEffectConfig_getEffectSize = battle.BuffEffectConfig.getEffectSize
local BuffEffectConfig_getPlace = battle.BuffEffectConfig.getPlace
local BuffEffectConfig_getParam = battle.BuffEffectConfig.getParam
local BuffEffectConfig_isAtFront = battle.BuffEffectConfig.isAtFront
local BuffEffectConfig_getBlendFunc = battle.BuffEffectConfig.getBlendFunc

local BattleConfig_getEffectConfig = battle.BattleConfig.getEffectConfig
local BattleConfig_getSkillConfigs = battle.BattleConfig.getSkillConfigs
local BattleConfig_getBuffConfigs = battle.BattleConfig.getBuffConfigs

local _CachedPhaseEvent =
{
	casterId = 0,
	isComboSkill = false,
	isSubSkill = false,
	skillId = 0,
	skillUid = 0,
	t = 0,
	targetId = 0,
	triggerKey = "",
	updateToTime = 0,
	pos = 0,
}

function VisualEffect:ctor()
	cc(self):addComponent("components.behavior.SimpleEvent"):exportMethods()

	self.effectCaches = {}
	self.buffEffectCaches = {}

	self.effects = {}
	self.updateToTime = 0
	self.skillPhase = display.newNode() -- new Signal()
	self:addChild(self.skillPhase)
	cc(self.skillPhase):addComponent("components.behavior.SimpleEvent"):exportMethods()

	self.projectilePhase = display.newNode() -- new Signal()
	self:addChild(self.projectilePhase)
	cc(self.projectilePhase):addComponent("components.behavior.SimpleEvent"):exportMethods()

	-- self.settlementPhase = display.newNode() -- new Signal()
	-- self:addChild(self.settlementPhase)
	-- cc(self.settlementPhase):addComponent("components.behavior.EventProtocol"):exportMethods()

	self.buffPhase = display.newNode() -- new Signal()
	self:addChild(self.buffPhase)
	cc(self.buffPhase):addComponent("components.behavior.SimpleEvent"):exportMethods()

    self:enableNodeEvents()


    -- 新手战斗引导是否结束标记、默认没有
    NewerbattleguideController = app:getInst( "NewerbattleguideController" )
    self._newerBattleGuideEndedFlag = NewerbattleguideController:isNewerBattleGuideEnded() or false
    app:addCustomEventListener( Constant.BattleNewerGuideEndFlag, function()
        print( " ---------------->>>>>>>> BattleLoop _newerBattleGuideEndedFlag true" )
        self._newerBattleGuideEndedFlag = true
    end, self )
end

function VisualEffect:onEnter()
	_CachedPhaseEvent =
	{
		casterId = 0,
		isComboSkill = false,
		isSubSkill = false,
		skillId = 0,
		skillUid = 0,
		t = 0,
		targetId = 0,
		triggerKey = "",
		updateToTime = 0,
		pos = 0,
	}
end

function VisualEffect:onExit()
    self:stop()
	self:clearEffectCache()
	self:clearBuffEffectCache()

	self.battleController = nil
	self.rewinded = nil
	self.fastforward = nil
	self.onHit = nil
	self.onCancel = nil
	self.onBuff = nil
	self.onSummon = nil
	self.onTransform = nil

	_CachedPhaseEvent =
	{
		casterId = 0,
		isComboSkill = false,
		isSubSkill = false,
		skillId = 0,
		skillUid = 0,
		t = 0,
		targetId = 0,
		triggerKey = "",
		updateToTime = 0,
		pos = 0,
	}
end

function VisualEffect:init(params)
	self.battleController = params.battleController
	local battleLoop = params.battleController.model.mBattleLoop
	self.rewinded = battleLoop:getRewindedSignal()
	self.fastforward = battleLoop:getFastForwardSignal()
	self.onHit = battleLoop:getOnHitSignal()
	self.onCancel = battleLoop:getSkillCancelSignal()
	self.onBuff = battleLoop:getBuffSignal()
	self.onSummon = battleLoop:getOnSummonSignal()
	self.onTransform = battleLoop:getOnTransformSignal()
end

function VisualEffect:setNextUpdateTime(time)
	self.updateToTime = time
end

function VisualEffect.prepareLoadTriggers()
	--print("==========VisualEffect.prepareLoadTriggers============")
	VisualEffect.triggers = {}
	local battleConfig = battle.BattleConfig:getInstance()
	local skills = BattleConfig_getSkillConfigs(battleConfig)
	-- 通用技能释放闪光特效
	local SkillHintEffect = BattleConfig_getEffectConfig(battleConfig, Res.SkillHintEffectId)
	for k,skillCfg in pairs(skills) do
		local skillId = SkillConfig_getId(skillCfg)
		for _,effect in pairs(SkillConfig_getEffects(skillCfg)) do -- add skill effect
			local triggerKey = VisualEffect.skillTriggerKey(skillId, EffectConfig_getBengin(effect))
			if not VisualEffect.triggers[triggerKey] then
				VisualEffect.triggers[triggerKey] = {}
			end
			table.insert(VisualEffect.triggers[triggerKey], effect)
		end

		--summon
		local summonEffectCfg = SkillConfig_getSummonEffectCfg(skillCfg)
		if summonEffectCfg then
			local triggerKey = VisualEffect.skillTriggerKey(skillId, "on-summon")
			if not VisualEffect.triggers[triggerKey] then
				VisualEffect.triggers[triggerKey] = {}
			end
			table.insert(VisualEffect.triggers[triggerKey], summonEffectCfg)
		end

		--transform
		local transformEffectCfg = SkillConfig_getTransformEffectCfg(skillCfg)
		if transformEffectCfg then
			local triggerKey = VisualEffect.skillTriggerKey(skillId, "on-transform")
			if not VisualEffect.triggers[triggerKey] then
				VisualEffect.triggers[triggerKey] = {}
			end
			table.insert(VisualEffect.triggers[triggerKey], transformEffectCfg)
		end

		if SkillHintEffect then
			--给每个非普攻技能添加effect
			if not SkillConfig_isBasicAttack(skillCfg) then
				local triggerKey = VisualEffect.skillTriggerKey(skillId, EffectConfig_getBengin(SkillHintEffect))
					if not VisualEffect.triggers[triggerKey] then
					VisualEffect.triggers[triggerKey] = {}
				end
				table.insert(VisualEffect.triggers[triggerKey], SkillHintEffect)
			end
		end

		local index = 0
		for key, projectileCfg in pairs(SkillConfig_getProjectiles(skillCfg)) do
			local projectileTag = string.format("%d-%d", skillId, index)
			local triggerKey
			for key1, effect in pairs(ProjectileConfig_getEffects(projectileCfg)) do -- add projectile effects
				triggerKey = VisualEffect.projectileTriggerKey(projectileTag, EffectConfig_getBengin(effect))
				if not VisualEffect.triggers[triggerKey] then
					VisualEffect.triggers[triggerKey] = {}
				end
				table.insert(VisualEffect.triggers[triggerKey], effect)
			end
			local summonEffectCfg = ProjectileConfig_getSummonEffectCfg(projectileCfg)
			if summonEffectCfg then
				triggerKey = VisualEffect.projectileTriggerKey(ProjectileConfig_getId(projectileCfg), "on-summon")
				if not VisualEffect.triggers[triggerKey] then
					VisualEffect.triggers[triggerKey] = {}
				end
				table.insert(VisualEffect.triggers[triggerKey], summonEffectCfg)
			end
			index = index + 1
		end
	end

	local buffs = BattleConfig_getBuffConfigs(battleConfig)
	local buffEffectBengin = BuffEffectConfig_getBengin(battle.BuffEffectConfig)
	for _,buffCfg in pairs(buffs) do
		local buffEffectCfg = BuffConfig_getBuffEffectConfig(buffCfg)
		if buffEffectCfg then
			local triggerKey = VisualEffect.buffTriggerKey(BuffEffectConfig_getId(buffEffectCfg), buffEffectBengin)
			if not VisualEffect.triggers[triggerKey] then
				VisualEffect.triggers[triggerKey] = {}
			end
			table.insert(VisualEffect.triggers[triggerKey], buffEffectCfg)
		end
	end
end

function VisualEffect:start()
	if self.rewinded then
		self.rewinded:addRewinded(function(t)
			local toBeRemoved = {}
			for _,effect in pairs(self.effects) do
				if t < (effect.t or 0) then
					table.insert(toBeRemoved,effect)
				end
			end

			for _,effect in pairs(toBeRemoved) do
				self:removeEffect(effect)
			end
		end)
	end

	if self.fastforward then
		self.fastforward:addFastForward(function(t)
			self.updateToTime = t
		end)
	end

	self.skillPhase:addEventListener("SkillPhase", handler(self,VisualEffect.onSkillPhase))
	self.projectilePhase:addEventListener("ProjectilePhase", handler(self,VisualEffect.onProjectilePhase))
	self.buffPhase:addEventListener("BuffPhase", handler(self,VisualEffect.onBuffPhase))
	-- self.settlementPhaseBind = self.settlementPhase:addEventListener("SettlementPhase", handler(self,VisualEffect.onSettlementPhase))

	battle.NormalSkillFsm:Instance():onTransition(function(client, fromState, toState)
		local fromStateStr = Enums.NormalSkillState[fromState]
		local toStateStr = Enums.NormalSkillState[toState]
		self:skillHook(client, fromStateStr, toStateStr)
	end)

	battle.SubSkillFsm:Instance():onTransition(function(client, fromState, toState)
		local fromStateStr = Enums.NormalSkillState[fromState]
		local toStateStr = Enums.NormalSkillState[toState]
		self:skillHook(client, fromStateStr, toStateStr)
	end)

	local function onBuff(event)
		local t = event.t
		local phase = event.phase
		local buffId = event.buffId
		local buffUid = event.buffUid
		local casterId = event.casterId
		local bearerId = event.bearerId
--		print("onbuff buffId:",buffId,phase)
		self.buffPhase:dispatchEvent("BuffPhase",{t = t, buffId = buffId, buffUid = buffUid, casterId = casterId, bearerId = bearerId, triggerKey = VisualEffect.buffTriggerKey(buffId,phase)})
	end
	self.onBuff:addEventListener("EVENT_ON_BUFF",onBuff)

	local function onHit(event)
		local t = event.t
		local kind = event.kind
		local skillIdOrProjectileTag = event.skillIdOrProjectileTag
		local skillOrProjectileUid = event.skillOrProjectileUid
		local casterId = event.casterId
		local targetId = event.targetId
		local isSubSkill = event.isSubSkill
		local isComboSkill = event.isComboSkill
		local damage = event.damage
		-- print("----------onSkillHit---targetId---",toId)
		-- print("----------onSkillHit---targetId---",skill:targetId())
		if kind == Enums.EntityKind.EKind_Projectile then
			self.projectilePhase:dispatchEvent("ProjectilePhase",{t = t, casterId = casterId, targetId = targetId, triggerKey = VisualEffect.projectileTriggerKey(skillIdOrProjectileTag,"on-hit")})
		elseif kind == Enums.EntityKind.EKind_Skill then
			self.skillPhase:dispatchEvent("SkillPhase",{t = t, skillId = skillIdOrProjectileTag, skillUid = skillOrProjectileUid, casterId = casterId, targetId = targetId, isSubSkill = isSubSkill, isComboSkill = isComboSkill, triggerKey = VisualEffect.skillTriggerKey(skillIdOrProjectileTag,"on-hit")})
		elseif kind == Enums.EntityKind.EKind_Buff then
			--print("==========Enums.EntityKind.EKind_Buff skillId:",skillIdOrProjectileTag)
			--print("==========Enums.EntityKind.EKind_Buff skillUid:",skillOrProjectileUid)
			-- self.buffPhase:dispatchEvent({name = "BuffPhase", t = t, buffId = skillIdOrProjectileTag, buffUid = skillOrProjectileUid, casterId = casterId, bearerId = targetId, triggerKey = VisualEffect.buffTriggerKey(skillIdOrProjectileTag,"on-hit")})
			self.skillPhase:dispatchEvent("SkillPhase",{t = t, skillId = skillIdOrProjectileTag, skillUid = skillOrProjectileUid, casterId = casterId, targetId = targetId, isSubSkill = isSubSkill, isComboSkill = isComboSkill, triggerKey = VisualEffect.skillTriggerKey(skillIdOrProjectileTag,"on-hit")})
		else
			printError("unknown on-hit kind",kind)
		end

	end
	self.onHit:addEventListener("EVENT_ON_HIT",onHit)

	local function onSummon(event)
		local t = event.t
		local causeKind = event.causeKind
		local casterId = event.casterId
		local posList = event.posList
		local causeId = event.causeId
		local triggerKey
		if causeKind == Enums.EntityKind.EKind_Skill then
			triggerKey = VisualEffect.skillTriggerKey(causeId,"on-summon")
		elseif causeKind == Enums.EntityKind.EKind_Projectile then
			triggerKey = VisualEffect.projectileTriggerKey(causeId,"on-summon")
		end
--		print("-------onSummon triggerKey:", triggerKey)
		local effectCfgs = VisualEffect.triggers[triggerKey]
		if effectCfgs then
			for _, effectCfg in pairs(effectCfgs) do
				if effectCfg then
					for k, pos in pairs(posList) do
--						print("=============================onSummon=====spawnEffect=========================")
						local effect = self:spawnEffect(t, effectCfg, casterId, nil, pos) --todo
						if effect then
							table.insert(self.effects,effect)
						end
					end
				end
			end
		end
	end
	self.onSummon:addEventListener("EVENT_ON_SUMMON",onSummon)

	local onTransform = function(event)
		local t = event.t
		local skillId = event.skillId
		local casterId = event.casterId
		local triggerKey = VisualEffect.skillTriggerKey(skillId,"on-transform")
		local effectCfgs = VisualEffect.triggers[triggerKey]
		if effectCfgs then
			for _,effectCfg in pairs(effectCfgs) do
				if effectCfg and not tolua.isnull(effectCfg) then
					local effect = self:spawnEffect(t, effectCfg, casterId)
					if effect then
						table.insert(self.effects,effect)
					end
				end
			end
		end
	end
	self.onTransform:addEventListener("EVENT_ON_TRANSFORM",onTransform)

	-- local function onProjectileHit(event)
	-- 	local t = event.t
	-- 	local fromId = event.fromId
	-- 	local toId = event.toId
	-- 	local tag = event.projectileTag
	-- 	local damage = event.damage
	-- 	-- print("----------onProjectileHit---toId---",toId)
	-- 	self.projectilePhase:dispatchEvent({name = "ProjectilePhase", t = t, fromId = fromId, toId = toId, triggerKey = VisualEffect.projectileTriggerKey(tag,"on-hit")})
	-- end
	-- self.onHit:addEventListener("EVENT_ON_PROJECTILE_HIT",onProjectileHit)

	-- local function onSettlementHit(event)
	-- 	local t = event.t
	-- 	local skillUid = event.skillUid
	-- 	local skillId = event.skillId
	-- 	local fromId = event.fromId
	-- 	local toId = event.toId
	-- 	local damage = event.damage

	-- 	self.settlementPhase:dispatchEvent({name = "SettlementPhase", t = t, skillUid = skillUid, skillId = skillId,fromId = fromId, toId = toId, triggerKey = VisualEffect.skillTriggerKey(skillId,"on-hit")})
	-- end
	-- self.onHit:addEventListener("EVENT_ON_SETTLEMENT_HIT",onSettlementHit)

	local function skillCancel(event)
		local t = event.t or 0
		local skillId = event.skillId
		local skillUid = event.skillUid
		local casterId = event.casterId
		local targetId = event.targetId
		local isSubSkill = event.isSubSkill
		local isComboSkill = event.isComboSkill
		local reason = event.reason

		--todo 显示打断
		if reason == Enums.SkillCancelReason.mana then
			--todo 能量不足
			self:dispatchEvent(VisualEffect.Event_SKILL_CANCEL_NO_MANA,{skillId = skillId, casterId = casterId, targetId = targetId})
		elseif reason == Enums.SkillCancelReason.broken then
			self:dispatchEvent(VisualEffect.Event_SKILL_INTERRUPTED,{skillId = skillId, casterId = casterId, targetId = targetId})
		end
		self.skillPhase:dispatchEvent("SkillPhase",{t = t, skillId = skillId, skillUid = skillUid, casterId = casterId, targetId = targetId, isSubSkill = isSubSkill, isComboSkill = isComboSkill, triggerKey = VisualEffect.skillTriggerKey(skillId,"skill-cancelled")})
	end
	self.onCancel:addEventListener("EVENT_SKILL_CANCEL",skillCancel)
end

function VisualEffect:stop()
	for _,effect in pairs(self.effects) do
		self:removeEffect(effect)
	end
	battle.NormalSkillFsm:Instance():off()
	battle.SubSkillFsm:Instance():off()

	self:removeAllEventListeners()
	self.skillPhase:removeAllEventListeners()
	self.projectilePhase:removeAllEventListeners()
	self.buffPhase:removeAllEventListeners()
--	self.settlementPhase:removeAllEventListeners()
end

function VisualEffect:skillHook(skill, exitState, enterState)
	local ctx = Skill_ctx(skill)
	local t = State_currentTime(ctx)
	local id = Skill_id(skill)
	local uid = Skill_uid(skill)
	local unit = Skill_unit(skill)
	local casterId = Entity_getId(unit)
	local targetId = Skill_targetId(skill)
	local isSubSkill = Skill_getIsSubSkill(skill)
	local isComboSkill = Skill_isComboSkill(skill)
	local skillConfig = Skill_getConfig(skill)
	local updateToTime = self.updateToTime
	local releaseTargetPos = Skill_getReleaseTargetPoint(skill)

	_CachedPhaseEvent.t=t
	_CachedPhaseEvent.updateToTime=updateToTime
	_CachedPhaseEvent.skillId=id
	_CachedPhaseEvent.skillUid=uid
	_CachedPhaseEvent.casterId=casterId
	_CachedPhaseEvent.targetId=targetId
	_CachedPhaseEvent.isSubSkill=isSubSkill
	_CachedPhaseEvent.isComboSkill=isComboSkill
	_CachedPhaseEvent.skillConfig = skillConfig
	_CachedPhaseEvent.pos = nil
	_CachedPhaseEvent.isHaloActive = skill:isHaloActive()
	_CachedPhaseEvent.isHaloSkill = skillConfig:getChannelType() ==  Enums.ChannelType.ChannelType_Switch_By_Select

	if exitState then
		_CachedPhaseEvent.triggerKey=VisualEffect.skillTriggerKey(id, string.format("exit-%s", exitState))
		self.skillPhase:dispatchEvent("SkillPhase",_CachedPhaseEvent)
	end

	if enterState then
		_CachedPhaseEvent.triggerKey = VisualEffect.skillTriggerKey(id, string.format("enter-%s", enterState))
		self.skillPhase:dispatchEvent("SkillPhase", _CachedPhaseEvent)
	end

	if exitState == "release" then
		_CachedPhaseEvent.pos = releaseTargetPos
		_CachedPhaseEvent.triggerKey = VisualEffect.skillTriggerKey(id, "on-release")
		self.skillPhase:dispatchEvent("SkillPhase", _CachedPhaseEvent)
        if not self._newerBattleGuideEndedFlag then -- 新手战引导未结束？
--            print( " ---------------->>>>>>>> 新手战引导 on-release", id )
            NewerbattleguideController:triggerBattleGuideEvent( id, "on-release" )
        end
	end
end

function VisualEffect:bindEffect(skillUid, effectCfg, skillId, effect, endStr)
	local binding
	local function callback(event1)
		local skillUid1 = event1.skillUid
		local triggerKey1 = event1.triggerKey
		if skillUid ~= skillUid1 then
			return
		end
		if triggerKey1 == VisualEffect.skillTriggerKey(skillId, endStr)
			or triggerKey1 == VisualEffect.skillTriggerKey(skillId, "skill-cancelled") then
			self:removeEffect(effect)
		end
	end
	binding = self.skillPhase:addEventListener("SkillPhase", callback)
	if binding then
		local function callbcak1()
			if binding then
				self.skillPhase:removeEventListener(binding)
			end
		end
		effect:setRemoveCallBack(callbcak1)
	end
end

function VisualEffect:onSkillPhase(event)
	local casterId = event.casterId
	local targetId = event.targetId
	-- 在特效等级为低的情况下，不显示和我以及我的目标无关的特效
	if not EFFECT_ALL_SHOW and not (self.battleController:isAboutMe(casterId, targetId) or self.battleController:isAboutMyTarget(casterId, targetId)) then
		return
	end
	local t = event.t
	local skillId = event.skillId
	local skillUid = event.skillUid
	local triggerKey = event.triggerKey
	local isSubSkill = event.isSubSkill
	local isComboSkill = event.isComboSkill
	local updateToTime = event.updateToTime
	local skillCfg = event.skillConfig
	local pos = event.pos

	local isPass = false
	if updateToTime and math.abs(t - updateToTime) > Constant.BattleEffectRetainTime then
		isPass = true
	end

	if isPass then
		return
	end

	--print("-----------triggerKey:",triggerKey)
	--print("-----------skillId:",skillId)

	-- local skillUid = skill:uid()
	-- local skillId = skill:id()
	-- local casterId = skill:unit():getId()
	-- local targetId = skill:targetId()

	-- local isSubSkill = skill:getIsSubSkill() -- todo
	-- local isSubSkill = false -- todo

	local casterView = self.battleController.views[casterId]

	local effectCfgs = VisualEffect.triggers[triggerKey]
	if not effectCfgs then
		return
	end
	
	for _,effectCfg in pairs(effectCfgs) do
		if effectCfg then
			local effectId = EffectConfig_getId(effectCfg)
			local isSkillHintEffect = effectId == Res.SkillHintEffectId
			if isSkillHintEffect and isSubSkill then
				-- 子技能
			else
				if isSkillHintEffect and (not isSubSkill) then
					if casterView then
						-- 主技能
						--是否和我有关的判断
						if self.battleController:isAboutMe(casterId, targetId) then
							-- 主技能名称冒字
							-- print(event.isHaloActive,event.isHaloSkill)
							if event.isHaloSkill then
								if not event.isHaloActive then
									--这样只有打开光环的时候会显示技能名字
									casterView:playSkillNameEffect(L(SkillConfig_getName(skillCfg)), isComboSkill)
								end
							else
								casterView:playSkillNameEffect(L(SkillConfig_getName(skillCfg)), isComboSkill)
							end
						end
					end
				end

				if isSkillHintEffect then
					--不播放技能释放特效
					return
				end
				local effect = self:spawnEffect(t, effectCfg, casterId, targetId, pos, skillId)
				if effect then
					table.insert(self.effects,effect)
					local endStr = EffectConfig_getEnd(effectCfg)
					if endStr ~= "" then
						self:bindEffect(skillUid, effectCfg, skillId, effect, endStr)
					end
				end
			end	
		end
	end
end

function VisualEffect:onProjectilePhase(event)
	local casterId = event.casterId
	local targetId = event.targetId
	-- 在特效等级为低的情况下，不显示和我以及我的目标无关的特效
	if not EFFECT_ALL_SHOW and not (self.battleController:isAboutMe(casterId, targetId) or self.battleController:isAboutMyTarget(casterId, targetId)) then
		return
	end
	local t = event.t
	local triggerKey = event.triggerKey
	local effectCfgs = VisualEffect.triggers[triggerKey]
	if effectCfgs then
		for _,effectCfg in pairs(effectCfgs) do
			if effectCfg then
				local effect = self:spawnEffect(t, effectCfg, casterId, targetId)
				if effect then
					table.insert(self.effects,effect)
				end
			end
		end
	end
end

function VisualEffect:bindBuffEffect(buffUid, buffId, effect)
	local binding = nil
	local endStr = BuffEffectConfig_getEnd(battle.BuffEffectConfig) --battle.BuffEffectConfig:getEnd()
	local activeStr = BuffEffectConfig_getActive(battle.BuffEffectConfig) --battle.BuffEffectConfig:getActive()
	-- print("=====BuffEffectConfig_getEnd:",endStr)
	-- print("=====BuffEffectConfig_getActive:",activeStr)
	local function callback(event)
		-- local t = event.t
		-- local buffId1 = event.buffId
		local buffUid1 = event.buffUid
		-- local casterId1 = event.casterId
		-- local bearerId1 = event.bearerId
		local triggerKey1 = event.triggerKey

		-- t, skill1, triggerKey1
		if buffUid ~= buffUid1 then
			return
		end
		if triggerKey1 == VisualEffect.buffTriggerKey(buffId, endStr) then
			-- print("-----buffId end:",buffId)
			if binding then
				self.buffPhase:removeEventListener(binding)
			end
			-- self:removeEffect(effect)
			local function deadCallBack()
				self:removeEffect(effect)
			end
			effect:dead(deadCallBack)
		elseif triggerKey1 == VisualEffect.buffTriggerKey(buffId, activeStr) then
			--生效
			effect:playDoing()
		end
	end
	binding = self.buffPhase:addEventListener("BuffPhase", callback)

	if binding then
		local function callbcak()
			if binding then
				self.buffPhase:removeEventListener(binding)
			end
		end
		effect:setRemoveCallBack(callbcak)
	end
end

function VisualEffect:onBuffPhase(event)
	local casterId = event.casterId
	local bearerId = event.bearerId
	-- 在特效等级为低的情况下，不显示和我以及我的目标无关的特效
	if not EFFECT_ALL_SHOW and not (self.battleController:isAboutMe(casterId, targetId) or self.battleController:isAboutMyTarget(casterId, targetId)) then
		return
	end
	local t = event.t
	local buffId = event.buffId
	local buffUid = event.buffUid
	local triggerKey = event.triggerKey

	-- print("-------onProjectilePhase targetId:",targetId)
	local effectCfgs = VisualEffect.triggers[triggerKey]
	if effectCfgs then
		for _,effectCfg in pairs(effectCfgs) do
			if effectCfg then
				local effect = self:spawnBuffEffect(t, effectCfg, casterId, bearerId)
				if effect then
					table.insert(self.effects,effect)

					-- if effectCfg:getEnd() ~= "" then
						self:bindBuffEffect(buffUid, buffId, effect)
					-- end
				end
			end
		end
	end
end

-- function VisualEffect:onSettlementPhase(event)
-- 	local t = event.t
-- 	local triggerKey = event.triggerKey

-- 	local skillUid = event.skillUid
-- 	local skillId = event.skillId
-- 	local fromId = event.fromId
-- 	local toId = event.toId
-- 	-- print("-------onSettlementPhase toId:",toId)
-- 	local effectCfgs = VisualEffect.triggers[triggerKey]
-- 	if effectCfgs then
-- 		for _,effectCfg in pairs(effectCfgs) do
-- 			if effectCfg then
-- 				local effect = self:spawnEffect(t, effectCfg, fromId, toId)
-- 				if effect then
-- 					table.insert(self.effects,effect)
-- 				end
-- 			end
-- 		end
-- 	end
-- end

local clearEffectCacheCron
function VisualEffect:clearEffectCache()
	if USE_Effect_Cache then
		-- print("======VisualEffect:clearEffectCache==========")
		local caches = self.effectCaches
		local tempFunc = cc.isDead
		local effectToProcess = {}
		for _, effects in pairs(caches) do
			if effects then
				for _, effect in pairs(effects) do
					if not tempFunc(effect) then
						table.insert(effectToProcess, effect)
					end
				end
			end
		end
		local count = #effectToProcess
		local effect
		clearEffectCacheCron = scheduler.newCron(function()
			count = count or -1
			if count > 0 then
				effect = effectToProcess[count]
				if not tempFunc(effect) then
					effect:cleanup()
					effect:release()
				end
				count = count - 1
			elseif count == 0 then
				scheduler.cancelCron(clearEffectCacheCron)
				count = nil
			end
		end, 0.01, true)
		
		-- for k,v in pairs(self.effectCaches) do
		-- 	if v then
		-- 		for key,effect in pairs(v) do
		-- 			if not cc.isDead(effect) then
		-- 				effect:cleanup()
		-- 				effect:release()
		-- 			end
		-- 		end
		-- 		v = {}
		-- 	end
		-- end
		-- self.effectCaches = {}
	end
end

local clearBuffEffectCacheCron
function VisualEffect:clearBuffEffectCache()
	if USE_Buff_Effect_Cache then
		local caches = self.buffEffectCaches
		local tempFunc = cc.isDead
		local effectToProcess = {}
		for _, effects in pairs(caches) do
			if effects then
				for _, effect in pairs(effects) do
					if not tempFunc(effect) then
						table.insert(effectToProcess, effect)
					end
				end
			end
		end
		local count = #effectToProcess
		local effect
		clearBuffEffectCacheCron = scheduler.newCron(function()
			count = count or -1
			if count > 0 then
				effect = effectToProcess[count]
				if not tempFunc(effect) then
					effect:cleanup()
					effect:release()
				end
				count = count - 1
			elseif count == 0 then
				scheduler.cancelCron(clearBuffEffectCacheCron)
				count = nil
			end
		end, 0.01, true)

		-- for k,v in pairs(self.buffEffectCaches) do
		-- 	if v then
		-- 		for key,effect in pairs(v) do
		-- 			if not cc.isDead(effect) then
		-- 				effect:cleanup()
		-- 				effect:release()
		-- 			end
		-- 		end
		-- 		v = {}
		-- 	end
		-- end
		-- self.buffEffectCaches = {}
	end
end

function VisualEffect:getEffectInCache(effectId)
	if USE_Effect_Cache then
		if effectId then
			if not self.effectCaches[effectId] then
				self.effectCaches[effectId] = {}
			else
				local effect = nil
				for k,v in pairs(self.effectCaches[effectId]) do
					if v then
						effect = v
						self.effectCaches[effectId][k] = nil
						break
					end
				end
				return effect
			end
		end
	end
	return nil
end

function VisualEffect:getBuffEffectInCache(effectId)
	if USE_Buff_Effect_Cache then
		if effectId then
			if not self.buffEffectCaches[effectId] then
				self.buffEffectCaches[effectId] = {}
			else
				local effect = nil
				for k,v in pairs(self.buffEffectCaches[effectId]) do
					if v then
						effect = v
						self.buffEffectCaches[effectId][k] = nil
						break
					end
				end
				return effect
			end
		end
	end
	return nil
end

function VisualEffect:pushEffectCache(effect)
	if USE_Effect_Cache and cc.isAlive(effect) then
		local effectId = effect:getEffectId()
		-- print("===========2====effect.effectId:",effectId)
		-- effect:retain()
		effect:removeSelf(false)
		effect:clearAnimation()
		-- print("==========3=====effect.effectId:",effectId)
		if not self.effectCaches[effectId] then
			self.effectCaches[effectId] = {}
		end
		table.insert(self.effectCaches[effectId], effect)
	end
end

function VisualEffect:pushBuffEffectCache(effect)
	if USE_Buff_Effect_Cache and cc.isAlive(effect) then
		local effectId = effect:getEffectId()
		-- print("===========2====effect.effectId:",effectId)
		-- effect:retain()
		effect:removeSelf(false)
		effect:clearAnimation()
		-- print("==========3=====effect.effectId:",effectId)
		if not self.buffEffectCaches[effectId] then
			self.buffEffectCaches[effectId] = {}
		end
		table.insert(self.buffEffectCaches[effectId], effect)
	end
end

function VisualEffect:cacheEffectByCfg(cfg)
	if USE_Effect_Cache then
		local effectId = EffectConfig_getId(cfg) --cfg:getId()
		local objectConfig = EffectConfig_getObjectCfg(cfg) --cfg:getObjectCfg()
		local blendFunc = EffectConfig_getBlendFunc(cfg) --cfg:getBlendFunc()
		local linkerEffectIndex = EffectConfig_getLine(cfg)
		local effect = Effect.new({effectId = effectId, objectConfig = objectConfig, blendFunc = blendFunc, linkerEffectIndex = linkerEffectIndex})
		effect:retain()
		self:pushEffectCache(effect)
	end
end

function VisualEffect:spawnEffect(t, cfg, casterId, victimId, pos, skillId)
	if cc.isDead(cfg) then
		return
	end

	local isPosEffect = pos ~= nil and pos ~= 0
	local isOnceEffect = EffectConfig_getEnd(cfg) == ""
	local linkedEffectIndex = EffectConfig_getLine(cfg)
	local isLinkedEffect = linkedEffectIndex > 0
	local isHitEffect = EffectConfig_getBengin(cfg) == "on-hit"
	local zOrderType = EffectConfig_getZorder(cfg)
	local battleController = self.battleController
	local caster = battleController.views[casterId]
	local victim = battleController.views[victimId]

	local isSelfCaster = false
	local controlledEntityId = battleController.model:getControlledEntityId()

	-- TODO: id 取的有问题
	local casterEntityModel
	if not cc.isDead(caster) then
		local casterUnitModelId = caster:getUnitModelId()
		casterEntityModel = battleController:getEntityModelById(casterUnitModelId)
		if caster:getId() == controlledEntityId then
			isSelfCaster = true
		end
	end

	local isSelfVictim = false
	local victimEntityModel
	if not cc.isDead(victim) then
		local victimUnitModelId = victim:getUnitModelId()
		victimEntityModel = battleController:getEntityModelById(victimUnitModelId)
		if victim:getId() == controlledEntityId then
			isSelfVictim = true
		end
	end

	local sfxFilePath
	local sfxFile = EffectConfig_getSfxFile(cfg)
	if sfxFile and string.len(sfxFile) > 0 and casterEntityModel then
		sfxFilePath = casterEntityModel:getSfxFilePath(sfxFile)
	end

	local effectId = EffectConfig_getId(cfg)
	local effect
	if USE_Effect_Cache then
		effect = self:getEffectInCache(effectId)
	end
	if cc.isDead(effect)
	  or cc.isDead(effect:getArmature())
	  or cc.isDead(db.CCArmatureDisplay.getArmature(effect:getArmature())) then
		if not cc.isDead(effect) then
			effect:cleanup()
			effect:release()
		end
		local objectConfig = EffectConfig_getObjectCfg(cfg)
		local blendFunc = EffectConfig_getBlendFunc(cfg)
		effect = Effect.new({effectId = effectId, objectConfig = objectConfig, blendFunc = blendFunc, linkerEffectIndex = linkedEffectIndex })
		if USE_Effect_Cache then
			effect:retain()
		end
	end
	effect.t = t
	effect:setSfxFilePath(sfxFilePath)
	effect:setVisible(true)
	effect:setEffectOpacity(255) --恢复正常透明度

	local scale = 1.0
	if not cc.isDead(caster) then
		scale = caster:getScale()*caster:getEffectScale()*(EffectConfig_getEffectSize(cfg)*0.01)
	end
    effect:setScale(scale)

	if isSelfCaster or (isSelfVictim and isHitEffect) then
		effect:setVolume(Constant.BattleSelfSfxVolume)
	else
		effect:setVolume(Constant.BattleOtherSfxVolume)
	end

	if isOnceEffect then
		local isNeedEnd = effect:playOnce(function()
			self:removeEffect(effect)
		end)
		if isNeedEnd then
			return nil
		end
	else
		effect:playDefault()
	end

	local createSuccess = true

	local place = EffectConfig_getPlace(cfg)
	local param = EffectConfig_getParam(cfg)
	local offsetX = EffectConfig_getOffsetX(cfg)
	if isPosEffect then
		if zOrderType == 1 then
            --前景层特效
			self:addChild(effect)
			--如果不是自己的特效，需要透明70%
			if not isSelfCaster then
				effect:setEffectOpacity(Constant.BattleOtherEntityEffectOpacity)
			end
        else
            --背景层
			self.backLayer:addChild(effect)
        end
		if pos then
			pos = pos + offsetX
		end
		local x = LocationConfig:getPosOnEntityLayer(pos)
		if not x then
    		x = display.width/2.0
    	end
    	effect:setPositionX(x)
		if not cc.isDead(caster) then
    		effect:face(caster:facing())
		end
	elseif place == "field-center" then
		-- if caster then
		-- 	effect:setVolume(caster:getVolume())
		-- end
		if zOrderType == 1 then
            --前景层特效
			self:addChild(effect)
			--如果不是自己的特效，需要透明70%
			if not isSelfCaster then
				effect:setEffectOpacity(Constant.BattleOtherEntityEffectOpacity)
			end
        else
            --背景层
			self.backLayer:addChild(effect)
        end

		local x = LocationConfig:getPosOnEntityLayer(LocationConfig:getLogicCenterPos())
		if not x then
    		x = display.width/2.0
    	end

    	effect:setPositionX(x)
		if caster then
    		effect:face(caster:facing())
		end
	elseif place == "caster-pos" then
		if not cc.isDead(caster) then
			-- effect:setVolume(caster:getVolume())
			if zOrderType == 1 then
	            --前景层特效
				self:addChild(effect)
				--如果不是自己的特效，需要透明70%
				if not isSelfCaster then
					effect:setEffectOpacity(Constant.BattleOtherEntityEffectOpacity)
				end
	        else
	            --背景层
				self.backLayer:addChild(effect)
	        end
			local x,y = caster:getPosition()
			x = x + LocationConfig:getWidthOnEntityLayer(offsetX)
    		effect:setPosition(x,y)

			effect:face(caster:facing())
		else
			printError("can not find caster,effect create error!!!!!")
			createSuccess = false
		end
	elseif place == "caster-origin" then
		if not cc.isDead(caster) then
			--跟随人物移动
			local armaturePosX,armaturePosY = caster:getArmature():getPosition()
    		effect:setPosition(armaturePosX,armaturePosY)
			-- effect:setVolume(caster:getVolume())
			caster:addChild(effect)
			if zOrderType~=1 then
		        effect:setLocalZOrder(-1)
		    end
			effect:face(caster:facing())
			--朝向依赖父亲节点的effect，需要特殊处理
			caster:addEffectView(effect)
		else
			printError("can not find caster,effect create error!!!!!")
			createSuccess = false
		end
	elseif place == "victim-pos" then
		if not cc.isDead(victim) then
			-- effect:setVolume(victim:getVolume())
			if zOrderType == 1 then
	            --前景层特效
				self:addChild(effect)
				--如果不是自己的特效，需要透明70%
				if not isSelfCaster then
					effect:setEffectOpacity(Constant.BattleOtherEntityEffectOpacity)
				end
	        else
	            --背景层
				self.backLayer:addChild(effect)
	        end
			local x,y = victim:getPosition()
			x = x + LocationConfig:getWidthOnEntityLayer(offsetX)
    		effect:setPosition(x,y)
			if caster then
				effect:face(caster:facing())
			end
		else
			printError("can not find victim,effect create error!!!!!")
			createSuccess = false
		end
	elseif place == "victim-origin" then
		if not cc.isDead(victim) then
			--跟随人物移动
			local armaturePosX,armaturePosY = victim:getArmature():getPosition()
    		effect:setPosition(armaturePosX,armaturePosY)
			-- effect:setVolume(victim:getVolume())
			victim:addChild(effect)
			if zOrderType~=1 then
		        effect:setLocalZOrder(-1)
		    end
			if caster then
				effect:face(caster:facing())
			end
		else
			printError("can not find victim,effect create error!!!!!")
			createSuccess = false
		end
	elseif place == "caster-bone" then
		if not cc.isDead(caster) then
			local posX,posY = caster:getBoneLocalPos(param)
			effect:setPosition(posX,posY)
			-- effect:setVolume(caster:getVolume())
			caster:addChild(effect)
			if zOrderType~=1 then
		        effect:setLocalZOrder(-1)
		    end
			effect:setVisible(false)

			local duration = 9999

			local followAction = db.DBFollowBone:create(duration,caster:getArmature(),param)
			local showActions = {}
			table.insert(showActions,cc.DelayTime:create(0))
			table.insert(showActions,cc.Show:create())
			local showAction = cc.Sequence:create(showActions)
			local action = cc.Spawn:create(showAction,followAction)

			effect:runAction(action)
			effect:face(caster:facing())
			--朝向依赖父亲节点的effect，需要特殊处理
			caster:addEffectView(effect)
		else
			printError("can not find caster,effect create error!!!!!")
			createSuccess = false
		end
	elseif place == "caster-bone-pos" then
		if not cc.isDead(caster) then
			local posX,posY = caster:getBoneLocalPos(param)
			effect:setPosition(posX,posY)
			-- effect:setVolume(caster:getVolume())
			caster:addChild(effect)
			if zOrderType~=1 then
		        effect:setLocalZOrder(-1)
		    end
			effect:face(caster:facing())
			--朝向依赖父亲节点的effect，需要特殊处理
			caster:addEffectView(effect)
		else
			printError("can not find caster,effect create error!!!!!")
			createSuccess = false
		end
	elseif place == "victim-bone" then
		if not cc.isDead(victim) then
			local posX,posY = 0,0
			if param == "body" then
				posX,posY = victim:getHitLocalPos(param)
			else
				posX,posY = victim:getBoneLocalPos(param)
			end
			effect:setPosition(posX,posY)
			-- effect:setVolume(victim:getVolume())
			victim:addChild(effect)
			if zOrderType~=1 then
		        effect:setLocalZOrder(-1)
		    end
			effect:setVisible(false)

			local duration = 9999
			local followAction = db.DBFollowBone:create(duration,victim:getArmature(),param)
			local showActions = {}
			table.insert(showActions,cc.DelayTime:create(0))
			table.insert(showActions,cc.Show:create())
			local showAction = cc.Sequence:create(showActions)
			local action = cc.Spawn:create(showAction,followAction)
			effect:runAction(action)
			effect:face(victim:facing())
			--朝向依赖父亲节点的effect，需要特殊处理
			victim:addEffectView(effect)
		else
			printError("can not find victim,effect create error!!!!!")
			createSuccess = false
		end
	elseif place == "victim-bone-pos" then
		if not cc.isDead(victim) then
			local posX,posY = 0,0
			if param == "body" then
				posX,posY = victim:getHitLocalPos(param)
			else
				posX,posY = victim:getBoneLocalPos(param)
			end
			effect:setPosition(posX,posY)
			-- effect:setVolume(victim:getVolume())
			victim:addChild(effect)
			if zOrderType~=1 then
		        effect:setLocalZOrder(-1)
		    end
			effect:face(victim:facing())
			--朝向依赖父亲节点的effect，需要特殊处理
			victim:addEffectView(effect)
		else
			printError("can not find victim,effect create error!!!!!")
			createSuccess = false
		end
	else
		printError("effect create error!!!!!unknown place!!!",place)
		createSuccess = false
	end

	-- if createSuccess and effectId == Res.SkillHintEffectId then
	-- 	--黑屏效果
	-- 	if isSelfCaster then
	-- 		self.battleController:showMaskForReleaseEffect()
	-- 	end
	-- end

	if isLinkedEffect then
		if isOnceEffect then
			effect:playDefaultForLinkerEffect(victim, function()
				self:removeEffect(effect)
			end)
		else
			effect:playDefaultForLinkerEffect(victim)
		end

	end

	if createSuccess then
		return effect
	end
end

function VisualEffect:spawnBuffEffect(t, cfg, casterId, victimId)
	-- print("------------VisualEffect:spawnBuffEffect-------------")

	-- print("----casterId------",casterId)
	-- print("----victimId------",victimId)
	-- local caster = self.battleController.views[casterId]
	local victim = self.battleController.views[victimId]

	-- local casterEntity = self.battleController:getEntityModelById(caster:getUnitModelId())
	if not victim then
		return nil
	end

	-- local objectConfig = self.battleLoop:getObjectConfig(cfg:getObjectId())


	-- local objectConfig = cfg:getObjectCfg()
	local effectId = BuffEffectConfig_getId(cfg) --cfg:getId()
	local effect
	if USE_Buff_Effect_Cache then
		effect = self:getBuffEffectInCache(effectId)
	end
	if not effect then
		-- print("=====buffview new===effectId:===",effectId)
		local blendFunc = BuffEffectConfig_getBlendFunc(cfg)
		effect = BuffView.new({effectId = effectId, buffEffectConfig = cfg, blendFunc = blendFunc})
		if USE_Buff_Effect_Cache then
			effect:retain()
		end
	end
	effect.t = t

	-- local test = objectConfig:getDir() == "effect/warrior_seismicwave" and objectConfig:getAnimation() == "release"

	local scale = 1.0
	-- if test then
	-- 	print("============effect=========victim:getScale():",victim:getScale())
	-- 	print("============effect=========victim:getEffectScale():",victim:getEffectScale())
	-- end
	scale = victim:getScale()*victim:getEffectScale()*(BuffEffectConfig_getEffectSize(cfg) --[[cfg:getEffectSize()]]*0.01) -- *effectSize

    effect:setScale(scale)

	effect:start()

	local createSuccess = true

	local place = BuffEffectConfig_getPlace(cfg) --cfg:getPlace()
	local param = BuffEffectConfig_getParam(cfg) --cfg:getParam()
	local front = BuffEffectConfig_isAtFront(cfg) --cfg:isAtFront()
	-- effect:face(victim:facing())
	-- print("------------place:",place)
	if place == 1 then
		if victim then
			local armaturePosX,armaturePosY = victim:getArmature():getPosition()
			effect:setPosition(armaturePosX,armaturePosY)
			victim:addBuffView(effect, front)
			-- victim:addChild(effect)
			effect:face(victim:facing())
		else
			printError("can not find victim,effect create error!!!!!")
			createSuccess = false
		end
	elseif place == 2 then
		if victim then
			local posX,posY = victim:getBoneLocalPos(param)
			effect:setPosition(posX,posY)
			victim:addBuffView(effect, front)
			-- victim:addChild(effect)
			local duration = 9999
			local action = db.DBFollowBone:create(duration,victim:getArmature(),param)
			effect:runAction(action)
			effect:face(victim:facing())
			-- effect:face(victim:facing())
		else
			printError("can not find victim,effect create error!!!!!")
			createSuccess = false
		end
	else
		printError("effect create error!!!!!unknown place!!!",place)
		createSuccess = false
	end

	if createSuccess then
		return effect
	end

	return nil
end

function VisualEffect:removeEffect(effect)
	for k,v in pairs(self.effects) do
		if v == effect then
			-- table.remove(self.effects, k)
			self.effects[k] = nil
			break
		end
	end
	if effect.flagBuffEffect then
		if USE_Buff_Effect_Cache then
			self:pushBuffEffectCache(effect)
		else
			effect:removeSelf(true)
		end
	else
		if USE_Effect_Cache then
			self:pushEffectCache(effect)
		else
			effect:removeSelf(true)
		end
	end
end

function VisualEffect.skillTriggerKey(skillId,phase)
	return string.format("skill%d%s",skillId,phase)
end

function VisualEffect.projectileTriggerKey(projectileTag, phase)
	return string.format("projectile%s%s",projectileTag,phase)
end

function VisualEffect.buffTriggerKey(buffId, phase)
	return string.format("buf%d%s",buffId,phase)
end

return VisualEffect
